/*
	File:		EntityManager.cpp
	Course:		SGD 1303
	Author:		dmonroe
	Purpose:	CEntityManager class stores & maintains
				the game entities
*/


#include "EntityManager.h"
#include "IEntity.h"
#include <cassert>


//**************************************************
// SINGLETON!
//	- instantiate the static data member
/*static*/ CEntityManager* CEntityManager::s_pInstance = nullptr;

// GetInstance
//	- allocate the singleton instance ONCE
/*static*/ CEntityManager* CEntityManager::GetInstance( void )
{
	if( s_pInstance == nullptr )
		s_pInstance = new CEntityManager;

	return s_pInstance;
}

// DeleteInstance
//	- deallocate the singleton instance
/*static*/ void CEntityManager::DeleteInstance( void )
{
	delete s_pInstance;
	s_pInstance = nullptr;
}


//**************************************************
// CONSTRUCTOR
CEntityManager::CEntityManager(void)
{
	m_lEntities.reserve( 4 );
	m_bIterating = false;
}

//**************************************************
// DESTRUCTOR
CEntityManager::~CEntityManager(void)
{
}



//**************************************************
// AddEntity
//	- add the entity to the container
void CEntityManager::AddEntity( IEntity* ptr )
{
	// Validate the parameter
	assert( ptr != nullptr && "CEntityManager::AddEntity - parameter is null" );

	// Validate the iteration state
	assert( m_bIterating == false && "CEntityManager::AddEntity - cannot add while iterating" );



	// Add the entity
	ptr->AddRef();
	m_lEntities.push_back( ptr );
}

//**************************************************
// RemoveEntity
//	- remove the entity from the container
void CEntityManager::RemoveEntity( IEntity* ptr )
{
	// Validate the parameter
	assert( ptr != nullptr && "CEntityManager::RemoveEntity - parameter is null" );

	// Validate the iteration state
	assert( m_bIterating == false && "CEntityManager::RemoveEntity - cannot remove while iterating" );


	// Search for the entity
	for( EntityListIter iter = m_lEntities.begin(); iter != m_lEntities.end(); )
	{
		if( (*iter) == ptr )
		{
			// Release the reference!
			(*iter)->Release();

			// Remove the entity
			iter = m_lEntities.erase( iter );


			// Stop looking for duplicates (not likely)
			break;
		}
		else
			++iter;		// move to next node
	}
}


//**************************************************
// RemoveAll
//	- remove all entities from the container
void CEntityManager::RemoveAll( void )
{
	// Validate the iteration state
	assert( m_bIterating == false && "CEntityManager::RemoveAll - cannot remove while iterating" );

	// Release each entity
	for( EntityListIter iter = m_lEntities.begin(); 
			iter != m_lEntities.end(); ++iter )
	{
		(*iter)->Release();
	}


	// Remove everything
	m_lEntities.clear();
}

//**************************************************
// UpdateAll
//	- call the Update method of each entity
void CEntityManager::UpdateAll( float fElapsedTime )
{
	// Lock the iterator
	m_bIterating = true;

	// Iterate through the container
	for( EntityListIter iter = m_lEntities.begin(); 
			iter != m_lEntities.end(); ++iter )
	{
		// Call the Update method
		(*iter)->Update( fElapsedTime );
	}

	// Unlock
	m_bIterating = false;
}

//**************************************************
// CheckAllCollisions	
//	- check each entity for collision against 
//	  entities of a different type
void CEntityManager::CheckAllCollisions( void )
{
	// Lock the iterator
	m_bIterating = true;
	
	// Check each entity against the others
	for( EntityList::iterator iterI = m_lEntities.begin(); iterI != m_lEntities.end(); ++iterI )
	{
		for( EntityList::iterator iterJ = m_lEntities.begin(); iterJ != m_lEntities.end(); ++iterJ )
		{
			// If they are different types
			if( (*iterI)->GetType() != (*iterJ)->GetType() )
			{
				// Check for collision
				if( (*iterI)->CheckCollision( *iterJ ) == true )
					break;		// stop looping after one collision
			}
		}
	}

	// Unlock the iterator
	m_bIterating = false;
}

//**************************************************
// RenderAll
//	- call the Render method of each entity
void CEntityManager::RenderAll( void )
{
	// Lock the iterator
	m_bIterating = true;

	// Iterate through the container
	for( EntityListIter iter = m_lEntities.begin(); 
			iter != m_lEntities.end(); ++iter )
	{
		// Call the Render method
		(*iter)->Render();
	}

	// Unlock
	m_bIterating = false;
}
